
/**		
 * 
 *	uk.co.lmfm.guppy.view.components.core.form.ComboBox
 *	
 *	@version 1.00 | Jan 22, 2010
 *	@author Justin Windle
 *  
 **/
 
package uk.co.lmfm.guppy.view.components.core.form 
{
	import com.bit101.components.Label;
	import com.bit101.components.PushButton;

	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;

	/**
	 * ComboBox
	 */
	public class ComboBox extends Sprite 
	{
		//	----------------------------------------------------------------
		//	PRIVATE MEMBERS
		//	----------------------------------------------------------------

		private var _items : Vector.<ComboBoxItem> = new Vector.<ComboBoxItem>();
		private var _arrow : Shape = new Shape();
		private var _current : Sprite = new Sprite();		private var _dropDown : Sprite = new Sprite();
		private var _currentItem : ComboBoxItem;
		private var _label : Label = new Label();
		private var _default : PushButton = new PushButton();
		private var _index : Dictionary = new Dictionary();
		private var _open : Boolean;

		//	----------------------------------------------------------------
		//	CONSTRUCTOR
		//	----------------------------------------------------------------

		public function ComboBox(label : String = "")
		{
			_label.text = label;
			_current.y = _label.height;
			
			_default.label = label;
			_default.width = 110;
			_default.addEventListener(MouseEvent.CLICK, onButtonClicked);
			
			_dropDown.visible = false;

			_arrow.graphics.beginFill(0x666666);
			_arrow.graphics.moveTo(-3.5, -1.75);			_arrow.graphics.lineTo(3.5, -1.75);			_arrow.graphics.lineTo(0.0, 1.75);
			_arrow.graphics.lineTo(-3.5, -1.75);
			_arrow.graphics.endFill();
			
			_arrow.y = _current.y + _default.height * 0.5;
			
			_current.addChild(_default);
			addChild(_current);
			addChild(_dropDown);
			addChild(_label);
			addChild(_arrow);
		}

		//	----------------------------------------------------------------
		//	PUBLIC METHODS
		//	----------------------------------------------------------------

		public function open() : void
		{
			addEventListener(Event.ENTER_FRAME, addStageListener);
			_dropDown.y = _current.y + _current.height - 1;
			_dropDown.visible = true;
			_open = true;
		}

		public function close() : void
		{
			stage.removeEventListener(MouseEvent.CLICK, onStageClicked);
			_dropDown.visible = false;
			_open = false;
		}

		public function addItem(label : String, data : * = null) : ComboBoxItem
		{
			_default.visible = false;
			
			var item : ComboBoxItem = new ComboBoxItem(label, data);
			item.addEventListener(MouseEvent.CLICK, onItemSelected);
			item.width = _default.width;
			
			_index[item] = data;
			_items.push(item);
			
			if(!currentItem) currentItem = item;
			else sortItems();
			
			return item;
		}

		public function clear() : void
		{
			_items.length = 0;
			_default.visible = true;
			_index = new Dictionary();
			_currentItem = null;
			
			var item : ComboBoxItem;
			
			while(_dropDown.numChildren > 0)
			{
				item = _dropDown.removeChildAt(0) as ComboBoxItem;
				item.removeEventListener(MouseEvent.CLICK, onItemSelected);
				item = null;
			}
		}

		//	----------------------------------------------------------------
		//	PRIVATE METHODS
		//	----------------------------------------------------------------

		private function sortItems() : void
		{
			var item : ComboBoxItem;
			
			for (var i : int = 0, j : int = 0;i < _items.length;i++)
			{
				item = _items[i];
				item.width = _default.width;
				
				if(item == _currentItem)
				{
					item.y = 0;
					_current.addChild(_currentItem);
				}
				else
				{
					item.y = (item.height - 1) * j++;
					_dropDown.addChild(item);
				}
			}
		}

		//	----------------------------------------------------------------
		//	EVENT HANDLERS
		//	----------------------------------------------------------------

		private function onButtonClicked(event : MouseEvent) : void
		{
			_open ? close() : open();
		}

		private function addStageListener(event : Event) : void
		{
			removeEventListener(Event.ENTER_FRAME, addStageListener);
			stage.addEventListener(MouseEvent.CLICK, onStageClicked);
		}

		private function onStageClicked(event : MouseEvent) : void
		{
			close();
		}

		private function onItemSelected(event : MouseEvent) : void
		{
			currentItem = event.currentTarget as ComboBoxItem;
			dispatchEvent(new Event(Event.SELECT));
		}

		//	----------------------------------------------------------------
		//	PUBLIC ACCESSORS
		//	----------------------------------------------------------------

		override public function get width() : Number
		{
			return _default.width;
		}

		override public function set width(value : Number) : void
		{
			_default.width = value;
			_arrow.x = _default.width - 10;
			sortItems();
		}

		public function get currentItem() : ComboBoxItem
		{
			return _currentItem;
		}

		public function set currentItem(value : ComboBoxItem) : void
		{
			if(_currentItem)
			{
				_currentItem.removeEventListener(MouseEvent.CLICK, onButtonClicked);
				_currentItem.addEventListener(MouseEvent.CLICK, onItemSelected);
			}
			
			_currentItem = value;
			_currentItem.removeEventListener(MouseEvent.CLICK, onItemSelected);
			_currentItem.addEventListener(MouseEvent.CLICK, onButtonClicked);
			
			sortItems();
			close();
		}

		public function get label() : String
		{
			return _default.label;
		}

		public function set label(value : String) : void
		{
			_default.label = value;
			_label.text = value;
		}
	}
}
